package com.glSto.controller;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.glSto.domain.*;
import com.glSto.domain.Collection;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.HttpServerErrorException;
import org.springframework.web.client.ResourceAccessException;
import org.springframework.web.client.RestTemplate;

import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@RestController
@RequestMapping("api/Power.GULEISTO/GULEISTO")
public class CollectionController {
    private static final Logger collectionLogger = LoggerFactory.getLogger("com.glSto.controller.CollectionController.getTodoList");

    @Value("${collection.api.url}")
    private String EXTERNAL_API_URL;

    @Value("${server.root}")
    private String serverRoot;

    @Value("${original.system.approval.url}")
    private String originalSystemApprovalUrl;

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private ObjectMapper objectMapper;

    @GetMapping("/{appCode}/getCount")
    public int getTodoCount(@PathVariable String appCode, @RequestParam String userId) {
        String appKey = "stoApply";
        String accessToken = "5411706e6b4a662481bcbeed9f4aec60";
        long timestamp = 1750644948350L;

        // 构建接口URL
        String externalApiUrl = EXTERNAL_API_URL;
        externalApiUrl += "?userId=" + userId;
        externalApiUrl += "&appKey=" + appKey;
        externalApiUrl += "&timestamp=" + timestamp;
        externalApiUrl += "&accessToken=" + accessToken;
        externalApiUrl += "&pagination=false";

        try {
            // 添加请求日志
            collectionLogger.info("开始调用待办数量接口，用户ID: {}, URL: {}", userId, externalApiUrl);

            HttpHeaders headers = new HttpHeaders();
            headers.set("Accept", "application/json");
            HttpEntity<String> entity = new HttpEntity<>(headers);

            // 调用接口
            ResponseEntity<String> response = restTemplate.exchange(externalApiUrl, HttpMethod.GET, entity, String.class);
            String responseBody = response.getBody();
            if (responseBody == null) {
                collectionLogger.warn("接口调用返回空响应，用户ID: {}", userId);
                throw new RuntimeException("接口调用失败: 无响应数据");
            }
            JsonNode rootNode = objectMapper.readTree(responseBody);
            if ("failure".equals(rootNode.get("status").asText())) {
                String errorMsg = rootNode.has("msg") ? rootNode.get("msg").asText() : "未知错误";
                collectionLogger.warn("接口调用失败: {}", responseBody);
                throw new RuntimeException("接口调用失败: " + errorMsg);
            }
            JsonNode dataNode = rootNode.get("data");
            int count = (dataNode != null && dataNode.isArray()) ? dataNode.size() : 0;
            // 添加成功响应日志
            collectionLogger.info("成功获取待办数量，用户ID: {}, 数量: {}", userId, count);
            return count;
        } catch (Exception e) {
            collectionLogger.error("获取待办数量失败，用户ID: {}", userId, e);
            throw new RuntimeException("接口调用失败: " + e.getMessage());
        }
    }




    /**
     * 查询用户待办数据接口
     * 接口地址：http://server-root/{appCode}/todoListDatas?userId={userId}
     */
    private static final Map<String, String> FIELD_MAPPING;

    static {
        FIELD_MAPPING = new HashMap<>();
        FIELD_MAPPING.put("OPSHORTTEXT", "OPSHORTTEXT");
        FIELD_MAPPING.put("PREDTYPE", "PREDTYPE");
        FIELD_MAPPING.put("ID", "ID");
        FIELD_MAPPING.put("TYPE", "TYPE");
        FIELD_MAPPING.put("PREVOPACID", "PREVOPACID");
        FIELD_MAPPING.put("WORK", "WORK");
        FIELD_MAPPING.put("MAN", "MAN");
        FIELD_MAPPING.put("DURATIONHOURS", "DURATIONHOURS");
        FIELD_MAPPING.put("ACTIVITYCODE", "ACTIVITYCODE");
        FIELD_MAPPING.put("HAZARDCLASS", "HAZARDCLASS");
        FIELD_MAPPING.put("STATEDESC", "STATEDESC");
        FIELD_MAPPING.put("FLAG", "FLAG");
        FIELD_MAPPING.put("CONTRACTORCATEGORY", "CONTRACTORCATEGORY");
        FIELD_MAPPING.put("SUBACTIVITYCODE", "SUBACTIVITYCODE");
        FIELD_MAPPING.put("REMAIN_DRTN_HR_CNT", "REMAIN_DRTN_HR_CNT");
        FIELD_MAPPING.put("CONTRACTORRESPONSE", "CONTRACTORRESPONSE");
        FIELD_MAPPING.put("SEQ_NUM", "SEQ_NUM");
        FIELD_MAPPING.put("CONTRACTORRESPONSECODE", "CONTRACTORRESPONSECODE");
        FIELD_MAPPING.put("TOTAL_FLOAT_HR_CNT", "TOTAL_FLOAT_HR_CNT");
        FIELD_MAPPING.put("CONTRACTORRESPONSEID", "CONTRACTORRESPONSEID");
        FIELD_MAPPING.put("OPTDATE", "OPTDATE");
        FIELD_MAPPING.put("CONTRACTORID", "CONTRACTORID");
        FIELD_MAPPING.put("STATE", "STATE");
        FIELD_MAPPING.put("PREVOPACCODE", "PREVOPACCODE");
        FIELD_MAPPING.put("SPECIALRESOURCES", "SPECIALRESOURCES");
        FIELD_MAPPING.put("FID", "FID");
        FIELD_MAPPING.put("INSPECTOR", "INSPECTOR");
        FIELD_MAPPING.put("TARPHASES", "TARPHASES");
        FIELD_MAPPING.put("OPAC", "OPAC");
        FIELD_MAPPING.put("TARGET_DRTN_HR_CNT", "TARGET_DRTN_HR_CNT");
        FIELD_MAPPING.put("CONTRACTORNAME", "CONTRACTORNAME");
        FIELD_MAPPING.put("FREE_FLOAT_HR_CNT", "FREE_FLOAT_HR_CNT");
//        FIELD_MAPPING.put("PARENTID", "PARENTID");
        FIELD_MAPPING.put("originalSystemApprovalUrl", "originalSystemApprovalUrl");
    }


    @GetMapping("/{appCode}/todoListDatas")
    public Object getTodoList(@PathVariable String appCode, @RequestParam String userId) {
        try {
            List<JsonNode> sourceDataList = fetchSourceData(userId, appCode);

            List<Item> items = sourceDataList.stream()
                    .map(this::convertToItem)
                    .collect(Collectors.toList());

            List<Template> templates = generateTemplates();

            Collection collection = new Collection();
            collection.setVersion("1.0");
            collection.setHref(serverRoot+appCode+"/api/Power.GULEISTO/GULEISTO/todoListDatas");
            collection.setItems(items);
            collection.setTemplates(templates);

            TodoListResponse response = new TodoListResponse();
            response.setCollection(collection);
            return response;
        } catch (ExternalApiException e) { // 捕获自定义异常
            return new ResultResponse(500,false, e.getMessage(), Collections.emptyList());
        } catch (Exception e) {
            return new ResultResponse(500, false,e.getMessage(), Collections.emptyList());
        }
    }

    private List<JsonNode> fetchSourceData(String userId, String appCode) {
        // 1. 极简入参校验（只防关键空值）
        if (userId == null || userId.trim().isEmpty() || EXTERNAL_API_URL == null) {
            String errorMsg = "获取源数据失败：用户ID或接口地址不能为空";
            collectionLogger.error(errorMsg + "，用户ID={}, 应用代码={}", userId, appCode);
            throw new ExternalApiException(errorMsg);
        }

        // 2. 固定参数（保留核心，不做额外封装）
        String appKey = "stoApply";
        String accessToken = "5411706e6b4a662481bcbeed9f4aec60";
        long timestamp = 1750644948350L; // 若需固定则保留，无需改当前时间

        // 3. 简单URL拼接（避免复杂工具，兼容基础场景）
        String externalApiUrl = EXTERNAL_API_URL + "?userId=" + userId + "&appKey=" + appKey
                + "&timestamp=" + timestamp + "&accessToken=" + accessToken + "&pagination=false";
        collectionLogger.info("获取源数据请求：用户ID={}, 应用代码={}, URL={}", userId, appCode, externalApiUrl);

        try {
            // 4. 极简请求配置（无多余头，只保必要Accept）
            HttpHeaders headers = new HttpHeaders();
            headers.set("Accept", "application/json");
            HttpEntity<Void> entity = new HttpEntity<>(headers);

            // 5. 发起请求（直接调用，不做多余空判）
            ResponseEntity<String> response = restTemplate.exchange(
                    externalApiUrl, HttpMethod.GET, entity, String.class
            );

            // 6. 处理响应：先判状态码，再判null
            if (!response.getStatusCode().is2xxSuccessful()) {
                String errorMsg = "请求失败：外部接口返回状态码" + response.getStatusCode();
                collectionLogger.error(errorMsg + "，URL={}", externalApiUrl);
                throw new ExternalApiException(errorMsg);
            }

            // 7. 兼容接口返回null场景（直接判空抛错）
            String responseBody = response.getBody();
            if (responseBody == null || responseBody.trim().isEmpty()) {
                String errorMsg = "请求失败：外部接口返回空数据";
                collectionLogger.error(errorMsg + "，URL={}", externalApiUrl);
                throw new ExternalApiException(errorMsg);
            }

            // 8. 简单JSON解析（不做多层异常拆分，解析错直接抛）
            JsonNode rootNode = objectMapper.readTree(responseBody);
            // 处理业务失败（含null判断）
            if (rootNode.get("status") == null || "failure".equals(rootNode.get("status").asText())) {
                String errorMsg = rootNode.has("msg") ? rootNode.get("msg").asText() : "外部接口业务失败（无错误信息）";
                collectionLogger.error("请求失败：{}，URL={}", errorMsg, externalApiUrl);
                throw new ExternalApiException("请求失败：" + errorMsg);
            }

            // 9. 处理data节点（兼容null和非数组）
            JsonNode dataNode = rootNode.get("data");
            if (dataNode == null || !dataNode.isArray()) {
                collectionLogger.warn("源数据为空或格式错误，返回空列表，URL={}", externalApiUrl);
                return Collections.emptyList();
            }

            // 10. 极简数据转换
            List<JsonNode> sourceList = new ArrayList<>();
            for (JsonNode node : dataNode) {
                sourceList.add(node);
            }
            collectionLogger.info("获取源数据成功，条数={}，用户ID={}", sourceList.size(), userId);
            return sourceList;

        } catch (Exception e) {
            // 11. 所有异常统一捕获：直接拼错误信息抛出
            String errorMsg = "获取源数据失败：" + (e.getMessage() == null ? "未知错误" : e.getMessage());
            // 区分异常类型，日志只打关键信息
            if (e instanceof ResourceAccessException) {
                errorMsg = "获取源数据失败：网络异常（超时/不可达）";
            } else if (e instanceof HttpClientErrorException) {
                errorMsg = "获取源数据失败：请求参数错误";
            } else if (e instanceof HttpServerErrorException) {
                errorMsg = "获取源数据失败：外部服务异常";
            } else if (e instanceof com.fasterxml.jackson.core.JsonProcessingException) {
                errorMsg = "获取源数据失败：响应格式错误（非JSON）";
            }

            collectionLogger.error(errorMsg + "，URL={}, 用户ID={}, 异常={}", externalApiUrl, userId, e.getMessage());
            throw new ExternalApiException(errorMsg);
        }
    }


    public static class ExternalApiException extends RuntimeException {
        public ExternalApiException(String message) {
            super(message);
        }
    }

    private Item convertToItem(JsonNode sourceNode) {
        Item item = new Item();
        List<DataField> dataFields = new ArrayList<>();

        FIELD_MAPPING.forEach((sourceKey, targetName) -> {
            String value;
            if ("originalSystemApprovalUrl".equals(sourceKey)) {
                // 使用从配置文件读取的值
                value = originalSystemApprovalUrl;
            } else {
                JsonNode valueNode = sourceNode.get(sourceKey);
                value = valueNode != null ? valueNode.toString().replace("\"", "") : "";
            }
            dataFields.add(new DataField(targetName, value));
        });

        item.setData(dataFields);
        return item;
    }

    private List<Template> generateTemplates() {
        Template template = new Template();
        List<DataField> templateData = FIELD_MAPPING.values().stream()
                .map(name -> new DataField(name, ""))
                .collect(Collectors.toList());
        template.setData(templateData);
        return Collections.singletonList(template);
    }

}
